package com.sankuai.project.service;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @Author：YH
 * @Description：
 * @Date:Created in 2022/3/27 23:17
 */
@Component
@Slf4j
public class BatchRunRedisUtil {


    @Resource(name = "taskExecutor")
    private Executor taskExecutor;

    @Retryable(value = Exception.class, maxAttempts = 10, backoff = @Backoff(delay = 2000))
    public Map<Integer, Boolean> integerBooleanMap() {
        log.info("执行一次");
        int i = 10 / 0;
        return Maps.newHashMap();
//        long start = System.currentTimeMillis();
//        List<Integer> pageNum = new ArrayList<>();
//        for (int i = 0; i < 1000; i++) {
//            pageNum.add(i);
//        }
//        List<CompletableFuture<Map<Integer, Boolean>>> futures = pageNum.stream()
//                .map(x -> CompletableFuture.supplyAsync(() -> this.getDataFromRpcMethod(x),
//                        taskExecutor))
//                .collect(Collectors.toList());
//
//        CompletableFuture<Void> voidCompletableFuture =
//                CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
//        List<Map<Integer, Boolean>> result = futures.stream().map(this::tryAndGet).collect(Collectors.toList());
//        return (Map<Integer, Boolean>) result;
    }

    private Map<Integer, Boolean> tryAndGet(CompletableFuture<Map<Integer, Boolean>> mapCompletableFuture) {
        Map<Integer, Boolean> responseData = new HashMap<>();
        try {
            responseData = mapCompletableFuture.get(10, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | TimeoutException | ExecutionException e) {
            throw new RuntimeException();
        }
        return responseData;
    }

    private Map<Integer, Boolean> getDataFromRpcMethod(Integer x) {
        Map<Integer, Boolean> map = new HashMap<>();
        map.put(x, x % 2 == 0 ? true : false);
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return map;
    }

    @Resource
    private RedisTemplate<String, Object> stringRedisTemplate;

    //批量添加
    public void batchSet(Map<String, String> map) {
        stringRedisTemplate.opsForValue().multiSet(map);
    }

    //批量获取list
    public List<Object> batchGet(List<String> list) {
        List<Object> objectList = stringRedisTemplate.opsForValue().multiGet(list);
        return objectList;
    }

    //批量添加 并且设置失效时间
    public void batchSetOrExpire(Map<String, String> map, Long seconds) {
        RedisSerializer<String> serializer = stringRedisTemplate.getStringSerializer();
        stringRedisTemplate.executePipelined(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                map.forEach((key, value) -> {
                    connection.set(serializer.serialize(key), serializer.serialize(value),
                            Expiration.seconds(seconds), RedisStringCommands.SetOption.UPSERT);
                });
                return null;
            }
        }, serializer);
    }

    // Redis批量Delete
    public void batchDelete(List<String> list) {
        stringRedisTemplate.delete(list);
    }
}